#include "qvimedit.h"
//
/*  Save file as qvimedit.cpp  */
/*  incomming class name QVimedit */
//


MeSearchDlg::MeSearchDlg( QWidget* parent )
	: QWidget( parent )
{
	setupUi( this );
    shortcut_search = new QShortcut(QKeySequence("Ctrl+F"),this);
    connect(shortcut_search, SIGNAL(activated()),this, SLOT(SearchReplace()));
}

void MeSearchDlg::SearchReplace()
{
    if (isVisible()) {
      setVisible(false);
      return;
    } else {
      setVisible(true);
    }
}


QViScintilla::QViScintilla( QWidget* parent )
 : QsciScintilla(parent)
{
    WorkFonts.fromString(setter.value("DefaultFontsS").toString());
    posX = 0;
    posY = 0;
    LineStartSearch = -1;
    filenummer = 404;
    BackgroundColor = "#ffffff";
    setPaper(QColor(BackgroundColor));
    setFolding(QsciScintilla::BoxedFoldStyle);;
    setMarginLineNumbers(1,true);
    setAutoCompletionFillupsEnabled(false);
    setCaretLineBackgroundColor(QColor("#fffaac"));
    setSelectionBackgroundColor(QColor("#ffff00"));
    setSelectionForegroundColor(QColor("#ff0000"));
    setCaretLineVisible(true);
    ensureLineVisible(1); 
    QsciLexerHTML *htmllex = new QsciLexerHTML(this);
    setLexer(htmllex);
    setContextMenuPolicy(Qt::CustomContextMenu);
    connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(Owncontex(QPoint)));
    shortcut1 = new QShortcut(QKeySequence("Ctrl+S"),this);
    connect(shortcut1, SIGNAL(activated()),this, SLOT(SaveCurrentDoc()));
    shortcut11 = new QShortcut(QKeySequence("F11"),this);
    connect(shortcut11, SIGNAL(activated()),this, SLOT(UpdateIt()));
    connect(this, SIGNAL(cursorPositionChanged(int,int)),this, SLOT(CursorAtIndex(int,int)));
    
    
    shortcut_search = new QShortcut(QKeySequence("Ctrl+F"),this);
    connect(shortcut_search, SIGNAL(activated()),this, SLOT(SearchReplace()));
    
        searchdlg = new MeSearchDlg(this);  
        searchdlg->setVisible(false);
        searchdlg->setWindowFlags(Qt::Drawer);

        connect(searchdlg->dd1, SIGNAL(clicked()),this, SLOT(FinderReplace()));
        connect(searchdlg->dd2, SIGNAL(clicked()),this, SLOT(FinderReplace()));
        connect(searchdlg->dd3, SIGNAL(clicked()),this, SLOT(FinderReplace()));
        #if defined(Q_WS_MAC) 
        /* go lateral search sidecar */
        #endif
        
        
    StreamXHTML = NO_TEXT_FILE_PAGE;
    setText( StreamXHTML );
    CreateAction();
    StarterCompleter();
   

}
void QViScintilla::SearchReplace()
{
    qDebug() << "### SearchReplace ";
    if (searchdlg->isVisible()) {
      searchdlg->setVisible(false);
      return;
    }
    #if defined(Q_WS_MAC)
    /* mac lateral menu Qt::Drawer */
    searchdlg->setWindowFlags(Qt::Drawer);
    QPoint pos = searchdlg->pos();
    if (pos.x() < 0)
        pos.setX(0);
    if (pos.y() < 0)
        pos.setY(0);
    searchdlg->move(pos);
    #endif
    searchdlg->show();
    searchdlg->setVisible(true);
}

void QViScintilla::GotoNextResult()
{
    replace(REPLACETEXTER); 
    
               if (findNext()) {
               GotoNextResult();
               }
}

void QViScintilla::FinderReplace()
{
    QPushButton *ddbutton = qobject_cast<QPushButton *>(sender());
    qDebug() << "### sender "  << ddbutton->objectName();
    
    FIND_WORD = searchdlg->wquery->toPlainText();
    REPLACETEXTER = searchdlg->ramplace->toPlainText();
    bool regexx = searchdlg->ooregularex->isChecked();
    bool casesensitive = searchdlg->oosensi->isChecked();
    FindStartPosition = SendScintilla(SCI_GETCURRENTPOS);
    LineStartSearch = SendScintilla(SCI_LINEFROMPOSITION, FindStartPosition);
    bool having;
    
    
    /*
    
    // Find the first occurrence of a string.
bool QsciScintilla::findFirst(const QString &expr, bool re, bool cs, bool wo,
        bool wrap, bool forward, int line, int index, bool show)
{
    */
    
    if (ddbutton->objectName() == "dd3") {
        /* replace all */
        replace(REPLACETEXTER); 
        return;
    }
    if (ddbutton->objectName() == "dd2") {
        /* replace all */
        GotoNextResult();
        return;
    }
    if (ddbutton->objectName() == "dd1") {
        /* search */
         if (searchdlg->ssup->isChecked()) {
          having = findFirst(FIND_WORD,regexx,regexx,casesensitive,true,false,-1,-1,true);
         } else {
          having = findFirst(FIND_WORD,regexx,regexx,casesensitive,true,true,-1,-1,true);
        }
    }
    
}


void QViScintilla::CreateAction()
{
    
    visiblespace = new QAction(tr("Visible or not space"),this);
    visiblespace->setIcon(QIcon(QString::fromUtf8(":/img/next.png")));
    visiblespace->setStatusTip(tr("Visible or not space")); 
    visiblespace->setCheckable ( true );
    connect(visiblespace, SIGNAL(toggled(bool)), this,  SLOT(VisibleSpaceEditor(bool)));

    sourceactionBold = new QAction(this);
    sourceactionBold->setText(tr("Selected source text bold"));
    sourceactionBold->setIcon(QIcon(QString::fromUtf8(":/img/textbold.png")));
    sourceactionBold->setStatusTip(tr("Selected source text bold")); 
    connect(sourceactionBold, SIGNAL(triggered()), this,  SLOT(SetBoldSelected()));
    
    sourceactionItalic = new QAction(this);
    sourceactionItalic->setText(tr("Selected source text italic"));
    sourceactionItalic->setStatusTip(tr("Selected source text italic")); 
    sourceactionItalic->setIcon(QIcon(QString::fromUtf8(":/img/textitalic.png")));
    connect(sourceactionItalic, SIGNAL(triggered()), this,  SLOT(SetItalicSelected()));
    
    sourceReformatClipboardText = new QAction(this);
    sourceReformatClipboardText->setText(tr("Insert Clipboard Plain/Text html reforformat"));
    sourceReformatClipboardText->setStatusTip(tr("Insert Clipboard Plain/Text html reforformat")); 
    sourceReformatClipboardText->setIcon(QIcon(QString::fromUtf8(":/img/mail_replylist.png")));
    connect(sourceReformatClipboardText, SIGNAL(triggered()), this,  SLOT(RefPasteText()));
    
    sourceTidy = new QAction(this);
    sourceTidy->setText(tr("Clean Code Tidy F11"));
    sourceTidy->setStatusTip(tr("Clean Code Tidy F11")); 
    sourceTidy->setIcon(QIcon(QString::fromUtf8(":/img/wizard.png")));
    connect(sourceTidy, SIGNAL(triggered()), this,  SLOT(UpdateIt()));
    
    
    
    sourceInsertdate = new QAction(this);
    sourceInsertdate->setText(tr("Insert Current Time"));
    sourceInsertdate->setStatusTip(tr("Insert Current Time")); 
    sourceInsertdate->setIcon(QIcon(QString::fromUtf8(":/img/date_and_time.png")));
    connect(sourceInsertdate, SIGNAL(triggered()), this,  SLOT(InsertDateNow()));
    
    sourceInsertJava = new QAction(this);
    sourceInsertJava->setText(tr("Insert Java Script"));
    sourceInsertJava->setStatusTip(tr("Insert Java Script")); 
    connect(sourceInsertJava, SIGNAL(triggered()), this,  SLOT(InsertJavaNow()));
    
    
    sourceToParam = new QAction(this);
    sourceToParam->setText(tr("Selected text to paragraph"));
    sourceToParam->setIcon(QIcon(QString::fromUtf8(":/img/textpointer.png")));
    sourceToParam->setStatusTip(tr("Selected text to paragraph")); 
    connect(sourceToParam, SIGNAL(triggered()), this,  SLOT(SetToParaSelected()));
    
    
    
    
     sourceToh1 = new QAction(this);
    sourceToh1->setText(tr("Selected text to title h1"));
    sourceToh1->setStatusTip(tr("Selected text to title h1")); 
    connect(sourceToh1, SIGNAL(triggered()), this,  SLOT(SetToHTitSelected()));
    
    
}

QMenu *QViScintilla::OwnContextMenu()
{
    QMenu *TC = new QMenu(this); 
    TC->addAction(QIcon(QString::fromUtf8(":/img/editcopy.png")),tr( "Copy CTRL+C" ), this , SLOT( copy() ) );
    TC->addAction(QIcon(QString::fromUtf8(":/img/paste.png")),tr( "Paste CTRL+V" ), this , SLOT( paste() ) );
    TC->addAction(QIcon(QString::fromUtf8(":/img/cut.png")),tr( "Cut CTRL+X" ), this , SLOT( cut() ) );
    TC->addAction(tr( "Select All CTRL+A" ), this , SLOT( selectAll() ) );
    TC->addAction(QIcon(QString::fromUtf8(":/img/filefind.png")),tr( "Search or replace CTRL+F" ), this , SLOT( SearchReplace() ) );
    
    
    
    
    
    TC->addAction(sourceTidy);
    TC->addSeparator();
    TC->addAction(QIcon(QString::fromUtf8(":/img/undo.png")),tr( "Undo CTRL+Z" ), this , SLOT( undo() ) );
    TC->addAction(QIcon(QString::fromUtf8(":/img/redo.png")),tr( "Redo CTRL+Y" ), this , SLOT( redo() ) );
    TC->addSeparator();
    TC->addAction(QIcon(QString::fromUtf8(":/img/zoomin.png")),tr( "Zoom in CTRL+" ), this , SLOT( zoomIn() ) );
    TC->addAction(QIcon(QString::fromUtf8(":/img/zoomout.png")),tr( "Zoom out CTRL-" ), this , SLOT( zoomOut() ) );
    TC->addSeparator();
    TC->addAction(sourceactionBold);  
    TC->addAction(sourceactionItalic);
    TC->addAction(sourceReformatClipboardText); 
    TC->addAction(sourceToParam);
    TC->addAction(sourceToh1);
    TC->addAction(sourceInsertdate);
    TC->addAction(sourceInsertJava);
    TC->addSeparator();
    TC->addAction(visiblespace);
    return TC;
}

void  QViScintilla::Owncontex(QPoint)
{
    QMenu *UserMenu = OwnContextMenu();
    UserMenu->exec(QCursor::pos());
    delete UserMenu;
}

void QViScintilla::StarterCompleter()
{
    baseram = QApplication::clipboard();
    completer = new QCompleter();
    QStringListModel *listmodel = new QStringListModel(completer);
    listmodel->setStringList(ReadList());
    completer->setModel(listmodel);
    completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
    completer->setCaseSensitivity(Qt::CaseInsensitive);
    completer->setWidget(this);
    completer->setCompletionMode(QCompleter::PopupCompletion);
    completer->setCaseSensitivity(Qt::CaseSensitive);
    connect(completer, SIGNAL(activated(QString)), this, SLOT(insertCompletion(QString)));
    c = completer;
}

void QViScintilla::setText( const QString txt )
{
    if (StreamXHTML.size() > 0) {
        QsciScintilla::setText(txt);
    }
   
}





/* completer from qt4 make it */
void QViScintilla::CursorAtIndex(int line ,int cool )
{
    liner = line;
    positr = cool;
    /* start from connect(this, SIGNAL(cursorPositionChanged(int,int)),this, SLOT(CursorAtIndex(int,int))); */
    setAutoCompletionFillupsEnabled(false);
    int newPos = SendScintilla(SCI_GETCURRENTPOS);
    posX = SendScintilla(SCI_POINTXFROMPOSITION, 0, newPos);
    posY = SendScintilla(SCI_POINTYFROMPOSITION, 0, newPos);
    CURRENTWORD = TextUnderCursor(newPos);    /* bring getWord(int position) to public !!!!!  */
    ///////////qDebug() << "### word " << CURRENTWORD;   /* word piece on cursor */
}



void QViScintilla::insertCompletion( QString completion )
{
    if (c->widget() != this) {
        return;
    }
    int newPos = SendScintilla(SCI_GETCURRENTPOS);
    CURRENTWORD = TextUnderCursor(newPos); 
    int line = SendScintilla(SCI_LINEFROMPOSITION, newPos);
    int col = SendScintilla(SCI_GETCOLUMN, newPos);
    int cole = col + CURRENTWORD.length();
    ////////////qDebug() << "### line " << line << "-" << col;
   /////////// qDebug() << "### selezione " << cole << "-" << col; 
    ////////qDebug() << "### word " << CURRENTWORD; 
    setSelection(line,col,line,cole);
    if ( hasSelectedText() ) {
    cut();
        if (completion.endsWith(">")) {
            completion = completion.prepend("<"); 
        }
    insert(completion);
    } else {
         int extra = completion.length() - CURRENTWORD.length();
         insert(completion.right(extra));
    }
    
}

QStringList QViScintilla::ReadList() 
{
    QString parole = DDopen("_htmlwordslist.txt");
    return parole.split("\n");
}

void QViScintilla::SetBoldSelected()
{
       qDebug() << "### sci selectedText() " << selectedText();
        baseram->clear();
        cut();
        QString ctext = baseram->text();
        insert("<b>"+ctext+"</b>");  
}

void QViScintilla::keyPressEvent(QKeyEvent *e)
{
    
    if (c && c->popup()->isVisible()) {
        // The following keys are forwarded by the completer to the widget
       switch (e->key()) {
       case Qt::Key_Enter:
       case Qt::Key_Return:
       case Qt::Key_Escape:
       case Qt::Key_Backtab:
            e->ignore(); 
            return; // let the completer do default behavior
       default:
           break;
       }
    }
    
     bool isShortcut = ((e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_E); // CTRL+E
     if (!c || !isShortcut) {
     QsciScintillaBase::keyPressEvent(e); 
     }
     
     const bool ctrlOrShift = e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier);
     if (!c || (ctrlOrShift && CURRENTWORD.isEmpty())) {
        return;
     }
     static QString eow("~!@#$%^&*()_+{}|:\"?,./;'[]\\-="); // end of word
     bool hasModifier = (e->modifiers() != Qt::NoModifier) && !ctrlOrShift;
     QString completionPrefix = CURRENTWORD;
    
    if (!isShortcut && (hasModifier || CURRENTWORD.isEmpty()|| completionPrefix.length() < 2  || eow.contains(CURRENTWORD.right(1)))) {
        c->popup()->hide();
        return;
    }

     if (CURRENTWORD != c->completionPrefix()) {
        c->setCompletionPrefix(CURRENTWORD);
        c->popup()->setCurrentIndex(c->completionModel()->index(0, 0));
    }
    
    QRect cr = QRect (posX, posY ,20,20);
    cr.setWidth(c->popup()->sizeHintForColumn(0) + c->popup()->verticalScrollBar()->sizeHint().width());
    c->complete(cr); // popup it up!
}

void QViScintilla::InsertJavaNow()
{
    QDateTime timeru( QDateTime::currentDateTime() );
    QString ctext = "<script type=\"text/javascript\">\n";
    ctext.append("//<![CDATA[\n");
    ctext.append("/* Your script here ... */\n");
    ctext.append("\n");
    ctext.append("\n");
    ctext.append("\n");
    ctext.append("\n");
    ctext.append("//]]>\n");
    ctext.append("</script>\n");
    insert(ctext); 
}






void QViScintilla::InsertDateNow()
{
    QDateTime timeru( QDateTime::currentDateTime() );
    QString ctext = "<!-- "+timeru.toString()+" -->";
    insert(ctext); 
}


void QViScintilla::RefPasteText()
{
    QString ctext = baseram->text();
    ctext = ctext.replace("\n","</p><p>");
    ctext.prepend("<p>");
    ctext.append("</p>");
    ctext = Cleaner( ctext );
    insert(ctext); 
}

void QViScintilla::SetToParaSelected()
{
        baseram->clear();
        cut();
        QString ctext = baseram->text();
        insert("<p>"+ctext+"</p>");  
}

void QViScintilla::SetToHTitSelected()
{
        baseram->clear();
        cut();
        QString ctext = baseram->text();
        insert("<h1>"+ctext+"</h1>");  
}




void QViScintilla::SetItalicSelected()
{
        baseram->clear();
        cut();
        QString ctext = baseram->text();
        insert("<i>"+ctext+"</i>");  
}


void QViScintilla::SetUnderlineSelected()
{
        baseram->clear();
        cut();
        QString ctext = baseram->text();
        insert("<u>"+ctext+"</u>");  
}






void QViScintilla::VisibleSpaceEditor( bool set )
{
          if (set) {
          setWhitespaceVisibility(QsciScintilla::WsVisible);
          } else {
          setWhitespaceVisibility(QsciScintilla::WsInvisible);
          }
}








void QViScintilla::PaintNewText()
{
   setText(StreamXHTML);
}

QString QViScintilla::Cleaner( QString html4 )
{
    
    html4 = html4.replace("<html:","<");
    html4 = html4.replace("<xslt:","<");
    /////////////////qDebug() << "### QViScintilla Cleaner tidy run  ";
    const  QString tidicaches = QString("%2/.qtidy/").arg(QDir::homePath());
    QTidy *tidy = new QTidy();   /* QTidy  *tidy; */
    tidy->Init(tidicaches);  /* tidy cache remove on last event */
    return tidy->TidyCleanhtml(html4);
}

void QViScintilla::UpdateIt()
{
    SetNowSource(text());
}



void QViScintilla::SetNowSource(  QString txt )
{
    
    QsciScintilla::setText(txt);
    return;
    
    int volume = txt.size();
    
    if (txt.size() < 100 || !txt.contains("<p",Qt::CaseInsensitive)) {
        StreamXHTML = NO_TEXT_FILE_PAGE;
    } else {
        StreamXHTML = Cleaner(txt);
    }
    
    const QString idpage = QString("Art_%1").arg(filenummer);
    const QString stylehard = QString("background-color:%1;").arg(BackgroundColor);
    
    QString errorStr;
    int errorLine, errorColumn;
    QDomDocument doc;
    
    if (!doc.setContent(StreamXHTML,false, &errorStr, &errorLine, &errorColumn)) {
    StreamXHTML = QString("<div xmlns=\"http://www.w3.org/1999/xhtml\" id=\"%3\"  style=\"%4\" version=\"scite_noxml\" charsize=\"%2\" class=\"qtpage\">\n%1\n</div>").arg(StreamXHTML).arg(volume).arg(idpage).arg(stylehard);
    } else {
        
        QDomElement root = doc.documentElement();
        if (root.tagName() !="div") {
            root.setTagName("div"); 
        }
           root.setAttribute ("xmlns","http://www.w3.org/1999/xhtml");
           root.setAttribute ("class","qtpage");   
           root.setAttribute ("id",idpage);
           root.setAttribute ("style",stylehard);
           root.setAttribute ("version","scite_1");
           root.setAttribute ("charsize",volume);
        StreamXHTML = doc.toString(4);
        debugwrite("__lastincomming_vi.html",StreamXHTML);
        QTimer::singleShot(200, this, SLOT(PaintNewText()));
        return;
    }
    
    
    
    
    /////////qDebug() << "### QViScintilla::SetNowSource - ";
    StreamXHTML = HumanTextQuiet(StreamXHTML,4);
    debugwrite("__lastincomming_vi.html",StreamXHTML);
    QTimer::singleShot(200, this, SLOT(PaintNewText()));
    
}



void QViScintilla::SaveCurrentDoc()
{
    qDebug() << "### emit save doc ....................";
    emit SaveStreamer();
}



QViScintilla::~QViScintilla()
{
    
}